package verificateur;


import java.util.HashMap;

import math.Fraction;
import structureDonnee.Inequalite;
import structureDonnee.Invariant;
import structureDonnee.Node;


public class TransformToSimplex {
	
	Invariant inv;
	Inequalite ine;
	int coeff[][];
	int c[];
	int b[];
	int constant ;
	
	public TransformToSimplex(Invariant iv, Inequalite eq, int FormeCanonique){
		inv = iv;
		ine = eq;
		int m =  iv.getListIne().size();//m = nombre de inequalite dans invariant
		int n = 2 *( eq.getExpr().getListExpr().size()-1 );//n=2* nombre de variable dans un expression.car ajouter des variable d ecart pour  x = x'-x'', x'>=0,x''>=0, x est general
//		System.out.println(" m "+m+" n "+n);
		coeff = new int [m][n];	//Ax<=b, coeff = A
		c = new int[n]; //c = dans inequalite eq,expression: a(i)*x(i)+constant >=0
		b = new int[m];	//Ax<=b, b = b;	
		constant = (int)eq.getExpr().getListExpr().get(eq.getExpr().getListExpr().size()-1).asDouble();
//		System.out.println("constant= "+constant);
		for(int i=0;i<n/2;i++){
			c[i]=-(int )eq.getExpr().getListExpr().get(i).asDouble();
			c[i+n/2] = (int )eq.getExpr().getListExpr().get(i).asDouble();
		}

		for (int j = 0; j<m;j++)
			for (int k = 0 ; k< n/2 ; k++){
				coeff[j][k] = (int )iv.getListIne().get(j).getExpr().getListExpr().get(k).times(-1).asDouble();
				coeff[j][k+n/2] = (int )iv.getListIne().get(j).getExpr().getListExpr().get(k).asDouble();
			}

		for (int j = 0; j< m; j++)
			b[j] =(int) iv.getListIne().get(j).getExpr().getListExpr().get(eq.getExpr().getListExpr().size()-1).asDouble();
	}
	
	public TransformToSimplex (Invariant iv, Inequalite eq ){
		inv = iv;
		ine = eq;
		
		int m = iv.getListIne().size();//m = nombre de inequalite dans invariant
		int n = eq.getExpr().getListExpr().size()-1;//n= nombre de variable dans un expression.
		
		coeff = new int [m][n];	//Ax<=b, coeff = A
		c = new int[n]; //c = dans inequalite eq,expression: a(i)*x(i)+constant >=0
		b = new int[m];	//Ax<=b, b = b;	
		constant = -(int)eq.getExpr().getListExpr().get(n).asDouble();
		
		for(int i=0;i<n;i++)
			c[i]=(int )eq.getExpr().getListExpr().get(i).asDouble();
		
		for (int j = 0; j<m;j++)
			for (int k = 0 ; k< n ; k++)
				coeff[j][k] = (int )iv.getListIne().get(j).getExpr().getListExpr().get(k).times(-1).asDouble();

		for (int j = 0; j< m; j++)
			b[j] =(int) iv.getListIne().get(j).getExpr().getListExpr().get(n).asDouble();
	}
	
	
	public  double value(){
		if(Simplex.Intialisation_Simplex(this.coeff , this.b, this.c)!=null){
			double value = Simplex.LinearProgramming(Simplex.Intialisation_Simplex(this.coeff , this.b, this.c));
			value = -value + constant;
			System.out.println("VALUE: "+value);
			return value;
		}
		else{
			System.out.println("INVARIANT CONTRADICTOIRE!");
			return Double.POSITIVE_INFINITY;
		}
	}
	
	public HashMap<Integer,Fraction> solution(){
		return Simplex.solutionOptimale(coeff, b, c);
	}
	
	//verifier dans le cas de inequalite avec strict < ou >
	public boolean verifierStrict(){
		boolean verifie = true;
		if(solution()!=null){}
		else{return false;}
		HashMap<Integer,Fraction> so = this.solution(); // renvoyer la solution optimale de simplex
		for(int i = 0;i < so.size();i++) 
			System.out.println(so.get(i));
		
		int length = so.size();
		for(Inequalite ine: inv.getListIne()){
			if(ine.getStrict()){//si c'est une inequalite avec strict < ou >
				double valeurDeExprDeIne = 0;
				for(int i = 0;i<length;i++){//calcule la valeur de expression de cette inequalite
					double tmp = so.get(i).times(new Fraction (ine.getExpr().getListExpr().get(i))).asDouble();
					valeurDeExprDeIne = valeurDeExprDeIne + tmp;
				}
				valeurDeExprDeIne = valeurDeExprDeIne + ine.getExpr().getListExpr().get(length).asDouble();
				System.out.println(valeurDeExprDeIne);
				verifie = verifie & (valeurDeExprDeIne != 0); //si la valeur est equal au zero, et en meme temps inequalite est strict, FALSE
			}
		}
		return verifie;
	}
}
